package org.spring.aop;

import java.io.Serializable;

/**
 * TargetSource用于获取 AOP 调用的当前“目标”，如果没有环绕通知选择结束拦截器链本身，则将通过反射调用该目标。
 * <p>
 * 如果TargetSource是“静态的”，它将始终返回相同的目标，从而允许在 AOP 框架中进行优化。动态目标源可以支持池化、热交换等。
 * <p>
 * 应用程序开发人员通常不需要直接使用TargetSources ：这是一个 AOP 框架接口。
 *
 * @author 李坤
 * @date 2022/4/18 10:20
 */
public interface TargetSource extends Serializable {

    /**
     * 所有对 {@link #getTarget()} 的调用都会返回相同的对象吗？
     * <p>
     * 在这种情况下，不需要调用{@link #releaseTarget(Object)}，AOP 框架可以缓存{@link #getTarget()} 的返回值。
     *
     * @return {@code true} 如果目标是不可变的
     *
     * @see #getTarget
     */
    boolean isStatic();

    /**
     * 返回此 {@link TargetSource} 返回的目标类型。
     * <p>
     * 可以返回 {@code null}，尽管 {@code TargetSource} 的某些用法可能只适用于预定的目标类。
     *
     * @return 此 {@link TargetSource} 返回的目标类型
     */
    Class<?> getTargetClass();

    /**
     * 返回一个目标实例。在 AOP 框架调用 AOP 方法调用的“目标”之前立即调用。
     *
     * @return 包含连接点的目标对象，如果没有实际的目标实例，则为 {@code null}
     *
     * @throws Exception 如果无法解析目标对象
     */
    Object getTarget() throws Exception;

    /**
     * 释放从 {@link #getTarget()} 方法获得的给定目标对象（如果有）。
     *
     * @param target 通过调用 {@link #getTarget()} 获得的对象
     *
     * @throws Exception 如果无法释放对象
     */
    void releaseTarget(Object target) throws Exception;

}
